[XEN] Add CPUID hypervisor-info leaves at index 0x40000000.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 5 Jul 2006 17:48:41 +0000 (18:48 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 5 Jul 2006 17:48:41 +0000 (18:48 +0100)
Currently only a signature leaf is defined ("Xen\0").
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vmx/vmx.c
xen/arch/x86/traps.c
xen/include/asm-x86/processor.h

index 29f74e8a0f89c6f96ba5c215a53814b3126f5f00..3a214c17069760f6fdfe13293b02661af7c911f2 100644 (file)
@@ -962,8 +962,8 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
                 !vlapic_global_enabled((VLAPIC(v))) )
         {
             /* Since the apic is disabled, avoid any confusion 
-              about SMP cpus being available */
-           clear_bit(X86_FEATURE_APIC, &edx);
+               about SMP cpus being available */
+            clear_bit(X86_FEATURE_APIC, &edx);
         }
 
 #if CONFIG_PAGING_LEVELS < 3
@@ -974,52 +974,51 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
         if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
         {
             if ( !v->domain->arch.hvm_domain.pae_enabled )
-            {
-               clear_bit(X86_FEATURE_PAE, &edx);
-            }
+                clear_bit(X86_FEATURE_PAE, &edx);
             clear_bit(X86_FEATURE_PSE, &edx);
             clear_bit(X86_FEATURE_PSE36, &edx);
         }
-#endif 
+#endif
         /* Clear out reserved bits. */
         ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED;
         edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED;
 
         clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
 
-       /* Guest should only see one logical processor.
-        * See details on page 23 of AMD CPUID Specification. 
-       */
-       clear_bit(X86_FEATURE_HT, &edx);  /* clear the hyperthread bit */
-       ebx &= 0xFF00FFFF;  /* clear the logical processor count when HTT=0 */
-       ebx |= 0x00010000;  /* set to 1 just for precaution */
+        /* Guest should only see one logical processor.
+         * See details on page 23 of AMD CPUID Specification. 
+         */
+        clear_bit(X86_FEATURE_HT, &edx);  /* clear the hyperthread bit */
+        ebx &= 0xFF00FFFF;  /* clear the logical processor count when HTT=0 */
+        ebx |= 0x00010000;  /* set to 1 just for precaution */
 
-       /* Disable machine check architecture */
-       clear_bit(X86_FEATURE_MCA, &edx);
-       clear_bit(X86_FEATURE_MCE, &edx);
+        /* Disable machine check architecture */
+        clear_bit(X86_FEATURE_MCA, &edx);
+        clear_bit(X86_FEATURE_MCE, &edx);
     }
-    else if ( ( input > 0x00000005 ) && ( input < 0x80000000 ) )
+    else if ( (input > 0x00000005) && (input < 0x80000000) )
     {
-       eax = ebx = ecx = edx = 0x0;
+        if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
+            eax = ebx = ecx = edx = 0;
     }
     else if ( input == 0x80000001 )
     {
-       /* We duplicate some CPUID_00000001 code because many bits of 
-          CPUID_80000001_EDX overlaps with CPUID_00000001_EDX. */
+        /* We duplicate some CPUID_00000001 code because many bits of 
+           CPUID_80000001_EDX overlaps with CPUID_00000001_EDX. */
 
         if ( !hvm_apic_support(v->domain) ||
-            !vlapic_global_enabled((VLAPIC(v))) )
+             !vlapic_global_enabled((VLAPIC(v))) )
         {
             /* Since the apic is disabled, avoid any confusion 
-              about SMP cpus being available */
-           clear_bit(X86_FEATURE_APIC, &edx);
+               about SMP cpus being available */
+            clear_bit(X86_FEATURE_APIC, &edx);
         }
 
-       /* Clear the Cmp_Legacy bit 
-        * This bit is supposed to be zero when HTT = 0.
-        * See details on page 23 of AMD CPUID Specification. 
-       */
-       clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx);
+        /* Clear the Cmp_Legacy bit 
+         * This bit is supposed to be zero when HTT = 0.
+         * See details on page 23 of AMD CPUID Specification. 
+         */
+        clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx);
 
 #ifdef __i386__
         /* Mask feature for Intel ia32e or AMD long mode. */
@@ -1030,7 +1029,7 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
 #endif
 
 #if CONFIG_PAGING_LEVELS < 3
-       clear_bit(X86_FEATURE_NX & 31, &edx);
+        clear_bit(X86_FEATURE_NX & 31, &edx);
         clear_bit(X86_FEATURE_PAE, &edx);
         clear_bit(X86_FEATURE_PSE, &edx);
         clear_bit(X86_FEATURE_PSE36, &edx);
@@ -1039,29 +1038,29 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
         {
             if ( !v->domain->arch.hvm_domain.pae_enabled )
             {
-               clear_bit(X86_FEATURE_NX & 31, &edx);
-               clear_bit(X86_FEATURE_PAE, &edx);
+                clear_bit(X86_FEATURE_NX & 31, &edx);
+                clear_bit(X86_FEATURE_PAE, &edx);
             }
             clear_bit(X86_FEATURE_PSE, &edx);
             clear_bit(X86_FEATURE_PSE36, &edx);
         }
-#endif 
+#endif
 
         /* Make SVM feature invisible to the guest. */
         clear_bit(X86_FEATURE_SVME & 31, &ecx);
-       
-       /* So far, we do not support 3DNow for the guest. */
-       clear_bit(X86_FEATURE_3DNOW & 31, &edx);
-       clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx);
+
+        /* So far, we do not support 3DNow for the guest. */
+        clear_bit(X86_FEATURE_3DNOW & 31, &edx);
+        clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx);
     }
     else if ( ( input == 0x80000007 ) || ( input == 0x8000000A  ) )
     {
-       /* Mask out features of power management and SVM extension. */
-       eax = ebx = ecx = edx = 0;
+        /* Mask out features of power management and SVM extension. */
+        eax = ebx = ecx = edx = 0;
     }
     else if ( input == 0x80000008 )
     {
-       ecx &= 0xFFFFFF00; /* Make sure Number of CPU core is 1 when HTT=0 */
+        ecx &= 0xFFFFFF00; /* Make sure Number of CPU core is 1 when HTT=0 */
     }
 
     regs->eax = (unsigned long)eax;
@@ -1214,8 +1213,9 @@ static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
 }
 
 
-static void svm_get_prefix_info(struct vmcb_struct *vmcb, 
-               unsigned int dir, segment_selector_t **seg, unsigned int *asize)
+static void svm_get_prefix_info(
+    struct vmcb_struct *vmcb, 
+    unsigned int dir, segment_selector_t **seg, unsigned int *asize)
 {
     unsigned char inst[MAX_INST_LEN];
     int i;
@@ -1287,9 +1287,10 @@ static void svm_get_prefix_info(struct vmcb_struct *vmcb,
 
 
 /* Get the address of INS/OUTS instruction */
-static inline int svm_get_io_address(struct vcpu *v, 
-               struct cpu_user_regs *regs, unsigned int dir, 
-        unsigned long *count, unsigned long *addr)
+static inline int svm_get_io_address(
+    struct vcpu *v, 
+    struct cpu_user_regs *regs, unsigned int dir, 
+    unsigned long *count, unsigned long *addr)
 {
     unsigned long        reg;
     unsigned int         asize = 0;
index ed9f6815c02a7a0d07861cca0ec0256b695b86a2..f65aa009f2b069699a2f4c52b080fd0d75b0ab0c 100644 (file)
@@ -868,7 +868,7 @@ static void vmx_vmexit_do_cpuid(struct cpu_user_regs *regs)
         cpuid_count(input, count, &eax, &ebx, &ecx, &edx);
         eax &= NUM_CORES_RESET_MASK;  
     }
-    else
+    else if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
     {
         cpuid(input, &eax, &ebx, &ecx, &edx);
 
index 30cf54562526a0bb694cbc0c680d6871f76d0740..162b96d3389a59d18612f1ba70caa89c0f183ab9 100644 (file)
@@ -426,10 +426,32 @@ DO_ERROR_NOCODE(16, "fpu error", coprocessor_error)
 DO_ERROR(17, "alignment check", alignment_check)
 DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
 
+int cpuid_hypervisor_leaves(
+    uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+{
+    if ( (idx < 0x40000000) || (idx > 0x40000000) )
+        return 0;
+
+    switch ( idx - 0x40000000 )
+    {
+    case 0:
+        *eax = 0x40000000;
+        *ebx = 0x006e6558; /* "Xen\0" */
+        *ecx = *edx = 0;
+        break;
+
+    default:
+        BUG();
+    }
+
+    return 1;
+}
+
 static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
 {
     char signature[5], instr[2];
-    unsigned long a, b, c, d, eip;
+    uint32_t a, b, c, d;
+    unsigned long eip;
 
     a = regs->eax;
     b = regs->ebx;
@@ -466,6 +488,10 @@ static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
         if ( !IS_PRIV(current->domain) )
             clear_bit(X86_FEATURE_MTRR, &d);
     }
+    else
+    {
+        (void)cpuid_hypervisor_leaves(regs->eax, &a, &b, &c, &d);
+    }
 
     regs->eax = a;
     regs->ebx = b;
index c6b3247763b0ffb774a87f13003ec2c8f3fb139d..38c83304467d32699f0b702f77fd284845bd650d 100644 (file)
@@ -545,6 +545,9 @@ extern void mtrr_bp_init(void);
 
 extern void mcheck_init(struct cpuinfo_x86 *c);
 
+int cpuid_hypervisor_leaves(
+    uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ASM_X86_PROCESSOR_H */